package com.april.pattern.creational.singleton;

import org.junit.jupiter.api.Test;

import java.io.*;
import java.lang.reflect.Constructor;

/**
 * @author April
 * @version V1.0.0
 * @date 2019/06/23 09:26
 * @description 单例模式的测试
 */
public class SingletonTest {
    @Test
    public void singletonTestTest() {
        Thread instance1 = new Thread(new ObtainInstance());
        Thread instance2 = new Thread(new ObtainInstance());
        instance1.start();
        instance2.start();

        System.out.println("Main Instance:" + ThreadLocalInstance.getInstance());
        System.out.println("Main Instance:" + ThreadLocalInstance.getInstance());
        System.out.println("Main Instance:" + ThreadLocalInstance.getInstance());
        System.out.println("Main Instance:" + ThreadLocalInstance.getInstance());
        System.out.println("Program End");
    }

    /**
     * 破坏单例
     *
     * @throws IOException IOException
     * @throws ClassNotFoundException ClassNotFoundException
     */
    @Test
    public void destroySingletonBySerializationTest() throws IOException, ClassNotFoundException {
        HungrySingleton hungrySingleton = HungrySingleton.getInstance();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("F:\\singletonFile"));
        objectOutputStream.writeObject(hungrySingleton);

        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("F:\\singletonFile"));
        HungrySingleton readHungrySingleton = ((HungrySingleton) objectInputStream.readObject());

        System.out.println(hungrySingleton);
        System.out.println(readHungrySingleton);
        System.out.println(hungrySingleton == readHungrySingleton);
    }

    @Test
    public void destroyEnumInstanceBySerializationTest() throws IOException, ClassNotFoundException {
        EnumInstance enumInstance = EnumInstance.getInstance();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("F:\\singletonFile"));
        objectOutputStream.writeObject(enumInstance);

        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("F:\\singletonFile"));
        EnumInstance readEnumInstance = ((EnumInstance) objectInputStream.readObject());

        System.out.println(enumInstance);
        System.out.println(readEnumInstance);
        System.out.println(enumInstance == readEnumInstance);
    }

    @Test
    public void destroySingletonByReflectionTest() throws Exception {
        Class hungryClass = HungrySingleton.class;
        Constructor constructor = hungryClass.getDeclaredConstructor();
        constructor.setAccessible(true);

        HungrySingleton hungrySingleton = HungrySingleton.getInstance();
        HungrySingleton reflexHungrySingleton = ((HungrySingleton) constructor.newInstance());

        System.out.println(hungrySingleton);
        System.out.println(reflexHungrySingleton);
        System.out.println(hungrySingleton == reflexHungrySingleton);
    }

    @Test
    public void destroyEnumInstanceByReflectionTest() throws Exception {
        Class enumInstanceClass = EnumInstance.class;
        Constructor constructor = enumInstanceClass.getDeclaredConstructor(String.class, int.class);
        constructor.setAccessible(true);

        EnumInstance enumInstance = EnumInstance.getInstance();
        // 无法反序列化
        EnumInstance reflexEnumInstance = ((EnumInstance) constructor.newInstance("April", 9));

        System.out.println(enumInstance);
        System.out.println(reflexEnumInstance);
        System.out.println(enumInstance == reflexEnumInstance);
    }
}
